package com.chen.blue.service.business.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chen.blue.annotation.permission.DataPermission;
import com.chen.blue.container.PermissionFlag;
import com.chen.blue.converter.business.ContestApplyRecordConverter;
import com.chen.blue.dictionary.AuditDict;
import com.chen.blue.domain.delete.business.ContestApplyRecordDelete;
import com.chen.blue.domain.dto.business.ContestApplyRecordDto;
import com.chen.blue.domain.dto.business.update.ContestApplyRecordDtoEdit;
import com.chen.blue.domain.model.business.*;
import com.chen.blue.domain.model.system.DeptModel;
import com.chen.blue.domain.query.business.ContestApplyRecordQuery;
import com.chen.blue.domain.vo.business.ContestApplyRecordVo;
import com.chen.blue.exception.e.DtoNullException;
import com.chen.blue.mapper.business.ContestApplyRecordMapper;
import com.chen.blue.result.DataResult;
import com.chen.blue.service.business.*;
import com.chen.blue.service.candidate.CandidateInfoService;
import com.chen.blue.service.security.SecurityService;
import com.chen.blue.utils.PageInfoUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.netty.util.internal.MathUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 竞赛申请活动记录表 服务实现类
 * </p>
 *
 * @author CLT
 * @since 2024-05-23
 */
@Service("iContestApplyRecordService")
public class IContestApplyRecordServiceImpl extends ServiceImpl<ContestApplyRecordMapper, ContestApplyRecordModel> implements IContestApplyRecordService {

    @Resource
    private IContestApplyService iContestApplyService;

    @Resource
    private IContestPersonInfoHistoryService iContestPersonInfoHistoryService;

    @Resource
    private IContestResourceHistoryService iContestResourceHistoryService;

    @Resource
    private IContestResultHistoryService iContestResultHistoryService;

    @Override
    public boolean addContestApplyRecord(ContestApplyRecordDto contestApplyRecordDto) throws DtoNullException {

        if (Objects.isNull(contestApplyRecordDto)) {
            throw new DtoNullException("参数为空");
        }

        CandidateInfoService.setCreator(contestApplyRecordDto);

        return super.save(ContestApplyRecordConverter.dtoToModel(contestApplyRecordDto));

    }

    @Override
    public boolean deleteContestApplyRecord(ContestApplyRecordDelete contestApplyRecordDelete) throws DtoNullException {

        if (Objects.isNull(contestApplyRecordDelete)) {
            throw new DtoNullException("参数为空");
        }

        Map<String, Object> wrap = new HashMap<>();
        if (Objects.nonNull(contestApplyRecordDelete.getId())) {
            wrap.put("id", contestApplyRecordDelete.getId());
        }

        return Objects.nonNull(contestApplyRecordDelete.getIds()) ? super.removeByIds(contestApplyRecordDelete.getIds()) : super.removeByMap(wrap);

    }


    @Override
    public boolean updateContestApplyRecordById(ContestApplyRecordDtoEdit contestApplyRecordDtoEdit) throws DtoNullException {

        if (Objects.isNull(contestApplyRecordDtoEdit)) {
            throw new DtoNullException("参数为空");
        }

        CandidateInfoService.setUpdater(contestApplyRecordDtoEdit);

        return super.updateById(ContestApplyRecordConverter.dtoEditToModel(contestApplyRecordDtoEdit));

    }

    @DataPermission
    @Override
    public DataResult<List<ContestApplyRecordVo>> queryContestApplyRecord(ContestApplyRecordQuery contestApplyRecordQuery) throws DtoNullException {

        if (Objects.isNull(contestApplyRecordQuery)) {
            throw new DtoNullException("参数为空");
        }

        LambdaQueryWrapper<ContestApplyRecordModel> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(ContestApplyRecordModel::getCreateTime);

        List<ContestApplyRecordModel> contestApplyRecordModelList = super.list(wrapper);
        PageInfo<ContestApplyRecordModel> pageInfo = new PageInfo<>(contestApplyRecordModelList);
        PageHelper.clearPage();

        // 关闭数据权限
        PermissionFlag.set(false);

        List<ContestApplyRecordModel> temp = super.list(wrapper);

        /**
         * 统一结果返回(返回的数据和数据库查询的条数不一致所以自定义分页)
         */
        DataResult<List<ContestApplyRecordVo>> dataResult = new DataResult<>();
        List<ContestApplyRecordVo> data = getContestApplyVoResult(ContestApplyRecordConverter.modelToVoList(pageInfo.getList()), ContestApplyRecordConverter.modelToVoList(temp));

        if (Objects.nonNull(contestApplyRecordQuery.getPageNo()) && Objects.nonNull(contestApplyRecordQuery.getPageSize()))
            data = Objects.nonNull(data) && !data.isEmpty() ? getContestApplyVoResult(ContestApplyRecordConverter.modelToVoList(pageInfo.getList()), ContestApplyRecordConverter.modelToVoList(temp))
                    .stream().skip(Long.parseLong(String.valueOf(contestApplyRecordQuery.getPageNo())) - 1)
                    .limit(Long.parseLong(String.valueOf(contestApplyRecordQuery.getPageSize()))).collect(Collectors.toList()) : Collections.EMPTY_LIST;


        // 自定义分页（经过数据处理后，返回的数据可能和sql查询的数据数量不一致，导致分页出现问题）
        {
            int pageNo = contestApplyRecordQuery.getPageNo() != null ? contestApplyRecordQuery.getPageNo() : 1;
            int pageSize = contestApplyRecordQuery.getPageSize() != null ? contestApplyRecordQuery.getPageSize() : data.size();
            int total = data.size();
            int pages = (total % pageSize) != 0 ? ((total / pageSize) + 1) : (total / pageSize);
            boolean hasNextPage = (total > pageNo * pageSize);

            pageInfo.setPageNum(pageNo);
            pageInfo.setPageSize(pageSize);
            pageInfo.setTotal(total);
            pageInfo.setPages(pages);
            pageInfo.setHasNextPage(hasNextPage);
        }

        // 结果返回
        dataResult.setData(data);

        PageInfoUtil.setPageInfo(dataResult, pageInfo);

        return dataResult;

    }

    @Override
    public DataResult<List<ContestApplyRecordVo>> queryContestApplyRecordById(String relation, Integer stageCurrent) throws DtoNullException {

        if (Objects.isNull(relation) || Objects.isNull(stageCurrent)) {
            throw new DtoNullException("参数为空");
        }

        LambdaQueryWrapper<ContestApplyRecordModel> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ContestApplyRecordModel::getRelation, relation);
        wrapper.eq(ContestApplyRecordModel::getStageCurrent, stageCurrent);

        List<ContestApplyRecordModel> contestApplyRecordModels = super.list(wrapper);

        DataResult<List<ContestApplyRecordVo>> dataResult = new DataResult<>();
        dataResult.setData(ContestApplyRecordConverter.modelToVoList(contestApplyRecordModels));

        return dataResult;

    }

    @DataPermission
    @Override
    public DataResult<List<ContestApplyRecordVo>> queryContestApplyRecordByAuditPerson(ContestApplyRecordQuery contestApplyRecordQuery) throws DtoNullException {

        if (Objects.isNull(contestApplyRecordQuery)) {
            throw new DtoNullException("查询条件为空");
        }

        LambdaQueryWrapper<ContestApplyRecordModel> wrapper = new LambdaQueryWrapper<>();
        if (Objects.nonNull(contestApplyRecordQuery.getPageNo()) && Objects.nonNull(contestApplyRecordQuery.getPageSize())) {
            PageHelper.startPage(contestApplyRecordQuery.getPageNo(), contestApplyRecordQuery.getPageSize());
        }
        if (Objects.nonNull(contestApplyRecordQuery.getStageCurrent())) {
            wrapper.eq(ContestApplyRecordModel::getStageCurrent, contestApplyRecordQuery.getStageCurrent());
        }
        // 配合数据权限使用，过滤掉申请人的记录，只保留审核人的记录
        wrapper.notIn(ContestApplyRecordModel::getAuditStatus, AuditDict.ROLE_INNER_NO);
        wrapper.orderByDesc(ContestApplyRecordModel::getCreateTime);

        List<ContestApplyRecordModel> contestApplyRecordModelList = super.list(wrapper);
        PageInfo<ContestApplyRecordModel> pageInfo = new PageInfo<>(contestApplyRecordModelList);
        PageHelper.clearPage();

        // 关闭数据权限
        PermissionFlag.set(false);

        /**
         * 数据处理（添加applyid）
         */
        List<ContestApplyRecordVo> contestApplyRecordVos = ContestApplyRecordConverter.modelToVoList(pageInfo.getList());
        List<ContestApplyModel> temp = iContestApplyService.list();
        List<ContestApplyRecordVo> data = null;
        if (Objects.nonNull(contestApplyRecordVos) && !contestApplyRecordVos.isEmpty() && Objects.nonNull(temp) && !temp.isEmpty())
            data = contestApplyRecordVos.stream().peek(var1 -> {
                for (ContestApplyModel contestApplyModel : temp) {
                    if (var1.getRelation().equals(contestApplyModel.getRelation())) {
                        var1.setApplyId(contestApplyModel.getId());
                    }
                }
            }).sorted(Comparator.comparing(ContestApplyRecordVo::getCreateTime)).collect(Collectors.toList());


        /**
         * 统一结果返回
         */
        DataResult<List<ContestApplyRecordVo>> dataResult = new DataResult<>();
        dataResult.setData(Objects.nonNull(data) && !data.isEmpty() ? data : contestApplyRecordVos);
        PageInfoUtil.setPageInfo(dataResult, pageInfo);

        return dataResult;

    }

    @Override
    public DataResult<Map<String, Object>> queryContestApplyRecordById(Long recordId) throws DtoNullException {

        if (Objects.isNull(recordId))
            throw new DtoNullException("参数为空");

        Map<String, Object> data = new HashMap<>();

        // record信息（历史）
        ContestApplyRecordModel contestApplyRecordModel = super.getById(recordId);
        data.put("record", ContestApplyRecordConverter.modelToVo(contestApplyRecordModel));

        // 历史人员信息（一般是第二阶段）
        LambdaQueryWrapper<ContestPersonInfoHistoryModel> wrapperVar1 = new LambdaQueryWrapper<>();
        wrapperVar1.eq(ContestPersonInfoHistoryModel::getRecordId, recordId);
        List<ContestPersonInfoHistoryModel> personInfoHistoryModelList = iContestPersonInfoHistoryService.list(wrapperVar1);
        data.put("persons", personInfoHistoryModelList);

        // 资源文件历史信息（一般是第一阶段）
        LambdaQueryWrapper<ContestResourceHistoryModel> wrapperVar2 = new LambdaQueryWrapper<>();
        wrapperVar2.eq(ContestResourceHistoryModel::getRecordId, recordId);
        List<ContestResourceHistoryModel> contestResourceHistoryModelList = iContestResourceHistoryService.list(wrapperVar2);
        data.put("resources", contestResourceHistoryModelList);

        // 比赛结果历史信息（一般是第三阶段）
        LambdaQueryWrapper<ContestResultHistoryModel> wrapperVar3 = new LambdaQueryWrapper<>();
        wrapperVar3.eq(ContestResultHistoryModel::getRecordId, recordId);
        List<ContestResultHistoryModel> contestResultHistoryModelList = iContestResultHistoryService.list(wrapperVar3);
        data.put("results", contestResultHistoryModelList);

        /**
         * 统一返回结果
         */
        DataResult<Map<String, Object>> dataResult = new DataResult<>();
        dataResult.setData(data);

        return dataResult;

    }


    /**
     * 以下三个方法是将审核记录分成三个阶段展示
     *
     * @param data
     * @return
     */
    protected ContestApplyRecordVo getLastContestApplyVo(List<ContestApplyRecordVo> data) {

        if (Objects.isNull(data) || data.isEmpty()) {
            return null;
        }

        double maxVersion = 0;
        ContestApplyRecordVo maxVersionContestRecordVo = null;
        for (ContestApplyRecordVo contestApplyRecordVo : data) {
            double temp = Math.max(maxVersion, Double.parseDouble(contestApplyRecordVo.getVersion()));
            if (temp != maxVersion) {
                maxVersion = temp;
                maxVersionContestRecordVo = contestApplyRecordVo;
            }
        }

        return maxVersionContestRecordVo;

    }

    protected List<ContestApplyRecordVo> getLastContestApplyVoByVersion(Set<Long> relationIds, List<ContestApplyRecordVo> data) {

        if (Objects.isNull(relationIds) || relationIds.isEmpty() || Objects.isNull(data) || data.isEmpty()) return null;

        List<ContestApplyRecordVo> tempDataOne = new ArrayList<>();
        for (Long relationId : relationIds) {
            List<ContestApplyRecordVo> collect = data.stream().filter(var4 -> var4.getRelation().equals(relationId)).collect(Collectors.toList());
            ContestApplyRecordVo lastContestApplyVo = getLastContestApplyVo(collect);
            tempDataOne.add(lastContestApplyVo);
        }

        return tempDataOne;

    }

    protected List<ContestApplyRecordVo> getContestApplyVoResult(List<ContestApplyRecordVo> contestApplyRecordVos, List<ContestApplyRecordVo> temp) {

        if (Objects.isNull(contestApplyRecordVos) || contestApplyRecordVos.isEmpty()) return null;

        Set<Long> relationIds = contestApplyRecordVos.stream().map(obj -> obj.getRelation()).collect(Collectors.toSet());

        List<ContestApplyRecordVo> versionOne = temp.stream().filter(var1 -> var1.getStageCurrent().equals(1)).collect(Collectors.toList());
        List<ContestApplyRecordVo> data1 = getLastContestApplyVoByVersion(relationIds, versionOne);

        List<ContestApplyRecordVo> versionTwo = temp.stream().filter(var2 -> var2.getStageCurrent().equals(2)).collect(Collectors.toList());
        List<ContestApplyRecordVo> data2 = getLastContestApplyVoByVersion(relationIds, versionTwo);

        List<ContestApplyRecordVo> versionThree = temp.stream().filter(var3 -> var3.getStageCurrent().equals(3)).collect(Collectors.toList());
        List<ContestApplyRecordVo> data3 = getLastContestApplyVoByVersion(relationIds, versionThree);


        List<ContestApplyRecordVo> data = new ArrayList<>();
        if (Objects.nonNull(data1)) {
            for (ContestApplyRecordVo contestApplyRecordVo : data1) {

                if (Objects.nonNull(contestApplyRecordVo))
                    data.add(contestApplyRecordVo);

            }
        }

        if (Objects.nonNull(data2)) {
            for (ContestApplyRecordVo contestApplyRecordVo : data2) {

                if (Objects.nonNull(contestApplyRecordVo))
                    data.add(contestApplyRecordVo);

            }
        }

        if (Objects.nonNull(data3)) {
            for (ContestApplyRecordVo contestApplyRecordVo : data3) {

                if (Objects.nonNull(contestApplyRecordVo))
                    data.add(contestApplyRecordVo);

            }
        }

        return data;

    }

}
